﻿using Kernel.EF.Demo.Sqlite;
using Microsoft.AspNetCore.OData;
using Microsoft.OData.Edm;
using Microsoft.OData.ModelBuilder;
using ODataRoutingSample.Models;

namespace WebAPI.Configure;

public static class ODataCoreExtensions
{
    public static void AddBuildinOData(this IMvcBuilder mvcBuilder)
    {
        IEdmModel edmDemo = GetEdmModel();
        IEdmModel edmSqlite = GetEdmSqlite();
        mvcBuilder.AddOData(opt => opt.Count().Filter().Expand().Select().OrderBy().SetMaxTop(5)
         .AddRouteComponents(edmDemo)
         .AddRouteComponents("sqlite", edmSqlite)
         );

    }

    public static void UseBuildinOData(this IApplicationBuilder app)
    {
        // Use odata route debug, /$odata
        app.UseODataRouteDebug();

        // If you want to use /$openapi, enable the middleware.
        //app.UseODataOpenApi();

        // Add OData /$query middleware
        app.UseODataQueryRequest();

        // Add the OData Batch middleware to support OData $Batch
        app.UseODataBatching();

    }

    private static IEdmModel GetEdmSqlite()
    {
        var builder = new ODataConventionModelBuilder();
        builder.EntitySet<WhiteList>("WhiteLists");
        return builder.GetEdmModel();
    }

    private static IEdmModel GetEdmModel()
    {
        var builder = new ODataConventionModelBuilder();
        builder.EntitySet<Product>("Products");
        builder.EntitySet<Person>("People").EntityType.HasKey(c => new { c.FirstName, c.LastName });

        // function with optional parameters
        var functionWithOptional = builder.EntityType<Product>().Collection.Function("GetWholeSalary").ReturnsCollectionFromEntitySet<Order>("Orders");
        functionWithOptional.Parameter<int>("minSalary");
        functionWithOptional.Parameter<int>("maxSalary").Optional();
        functionWithOptional.Parameter<string>("aveSalary").HasDefaultValue("129");

        // overload
        functionWithOptional = builder.EntityType<Product>().Collection.Function("GetWholeSalary").ReturnsCollectionFromEntitySet<Order>("Orders");
        functionWithOptional.Parameter<int>("minSalary");
        functionWithOptional.Parameter<double>("name");

        // overload
        functionWithOptional = builder.EntityType<Product>().Collection.Function("GetWholeSalary").ReturnsCollectionFromEntitySet<Order>("Orders");
        functionWithOptional.Parameter<string>("order");
        functionWithOptional.Parameter<string>("name");

        // function with only one parameter (optional)
        functionWithOptional = builder.EntityType<Product>().Collection.Function("GetOptional").ReturnsCollectionFromEntitySet<Order>("Orders");
        functionWithOptional.Parameter<string>("param").Optional();

        // unbound
        builder.Action("ResetData");

        // using attribute routing
        var unboundFunction = builder.Function("CalculateSalary").Returns<string>();
        unboundFunction.Parameter<int>("minSalary");
        unboundFunction.Parameter<int>("maxSalary").Optional();
        unboundFunction.Parameter<string>("wholeName").HasDefaultValue("abc");

        return builder.GetEdmModel();
    }

}
